package pro.shushi.pamirs.hr.core.service;

import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pro.shushi.pamirs.framework.connectors.data.sql.Pops;
import pro.shushi.pamirs.hr.api.enums.ApprovalStatusEnum;
import pro.shushi.pamirs.hr.api.enums.HrSimpleExpEnum;
import pro.shushi.pamirs.hr.api.model.biz.ExpenseBill;
import pro.shushi.pamirs.hr.api.model.biz.ExpenseBillDetail;
import pro.shushi.pamirs.hr.api.service.ExpenseBillService;
import pro.shushi.pamirs.meta.annotation.Fun;
import pro.shushi.pamirs.meta.annotation.Function;
import pro.shushi.pamirs.meta.api.Models;
import pro.shushi.pamirs.meta.common.exception.PamirsException;
import pro.shushi.pamirs.meta.common.util.ListUtils;

import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Fun(ExpenseBillService.FUN_NAMESPACE)
public class ExpenseBillServiceImpl implements ExpenseBillService {

    @Transactional
    @Override
    @Function
    public void update(ExpenseBill data) {
        // 校验方式2：销单金额与明细金额汇总是否一致.
        _checkAmount(data);

        // 保存数据
        data.updateById();
        List<ExpenseBillDetail> inputBillDetails = data.getBillDetails();
        List<ExpenseBillDetail> dbBillDetails = new ExpenseBillDetail().setBillCode(data.getCode()).queryList();
        if (CollectionUtils.isNotEmpty(dbBillDetails)) {
            List<Long> inputIds = ListUtils.transform(inputBillDetails, ExpenseBillDetail::getId);
            List<Long> dbIds = ListUtils.transform(dbBillDetails, ExpenseBillDetail::getId);
            Set<Long> deleteIds = Sets.difference(new HashSet<>(dbIds), new HashSet<>(inputIds));
            if (CollectionUtils.isNotEmpty(deleteIds)) {
                Models.data().deleteByWrapper(Pops.<ExpenseBillDetail>lambdaQuery()
                        .from(ExpenseBillDetail.MODEL_MODEL).in(ExpenseBillDetail::getId, deleteIds));
            }
        }
        data.fieldSave(ExpenseBill::getBillDetails);
    }

    /**
     * 该示例说明：提交数据校验数据.
     * _checkAmount 和 pro.shushi.pamirs.hr.core.action.ExpenseBillAction#create方法上的@Validation(check = "checkAmount") 作用一样
     *
     * 校验方式1：直接在方法内部显示调用checkAmount
     * @param data
     */
    private void _checkAmount(ExpenseBill data) {
        ExpenseBill dbExpenseBill = new ExpenseBill().setId(data.getId()).queryById();
        if (!ApprovalStatusEnum.NC.equals(dbExpenseBill.getApprovalStatus())) {
            throw PamirsException.construct(HrSimpleExpEnum.EXPENSE_BILL_STATUS_NOT_NC).errThrow();
        }

        if (CollectionUtils.isEmpty(data.getBillDetails())) {
            throw PamirsException.construct(HrSimpleExpEnum.EXPENSE_BILL_DETAIL_NULL).errThrow();
        }
        BigDecimal totalAmount = new BigDecimal("0.0");
        for (ExpenseBillDetail detail: data.getBillDetails()) {
            totalAmount = totalAmount.add(detail.getAmount());
        }
        if (data.getAmount().compareTo(totalAmount) != 0) {
            throw PamirsException.construct(HrSimpleExpEnum.EXPENSE_BILL_AMOUNT_ERROR).errThrow();
        }
    }

}
